﻿using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;

namespace OpenLS.Spreadsheet.Formats.Biff.Records
{
    internal struct FtCmo
    {
        private bool _fDefaultSize;
        private bool _reserved;
        private bool _unused1;
        private bool _unused2;
        private bool _unused3;
        private bool _unused4;
        private bool _unused5;
        private bool _unused6 ;
        private byte[] __unusedbytes ;
        private byte[] unusedbytes

        {
            get
            {
                if (__unusedbytes == null)
                    __unusedbytes = new byte[12];
                return __unusedbytes;
            }
        }
        private bool fDisabled;
        private bool fLocked ;
        private bool fPrint;
        private bool fPublished;
        private bool fRecalcObj;
        private bool fRecalcObjAlways;
        private bool fUIObj;
        public ushort id;
        public FtCmoObjectType ot;
        private bool unused7;

        public void Read(BinaryReader reader)
        {
            ushort ft = reader.ReadUInt16();
            Contract.Assert(ft == 0x15);
            ushort cb = reader.ReadUInt16();
            Contract.Assert(cb == 0x12);
            ot = (FtCmoObjectType) reader.ReadUInt16();
            id = reader.ReadUInt16();
            ushort ap = reader.ReadUInt16();
            fLocked = (ap & 0x0001) != 0;
            _reserved = (ap & 0x0002) != 0;
            _fDefaultSize = (ap & 0x0004) != 0;
            fPublished = (ap & 0x0008) != 0;
            fPrint = (ap & 0x0010) != 0;
            _unused1 = (ap & 0x0020) != 0;
            _unused2 = (ap & 0x0040) != 0;
            fDisabled = (ap & 0x0080) != 0;
            fUIObj = (ap & 0x0100) != 0;

            fRecalcObj = (ap & 0x0200) != 0;
            _unused3 = (ap & 0x0400) != 0;
            _unused4 = (ap & 0x0800) != 0;
            fRecalcObjAlways = (ap & 0x1000) != 0;
            _unused5 = (ap & 0x2000) != 0;
            _unused6 = (ap & 0x4000) != 0;
            unused7 = (ap & 0x8000) != 0;
            __unusedbytes = reader.ReadBytes(12);
        }

        public void Write(BinaryWriter writer)
        {
            ushort ft = 0x15;
            writer.Write(ft);

            ushort cb = 0x12;
            writer.Write(cb);
            writer.Write((ushort) ot);
            writer.Write(id);
            ushort ap = 0;
            if (fLocked)
                ap |= 0x01;
            if (fLocked)
                ap |= 0x0001;
            if (_reserved)
                ap |= 0x0002;
            if (_fDefaultSize)
                ap |= 0x0004;
            if (fPublished)
                ap |= 0x0008;
            if (fPrint)
                ap |= 0x0010;
            if (_unused1)
                ap |= 0x0020;
            if (_unused2)
                ap |= 0x0040;
            if (fDisabled)
                ap |= 0x0080;
            if (fUIObj)
                ap |= 0x0100;

            if (fRecalcObj)
                ap |= 0x0200;
            if (_unused3)
                ap |= 0x0400;
            if (_unused4)
                ap |= 0x0800;
            if (fRecalcObjAlways)
                ap |= 0x1000;
            if (_unused5)
                ap |= 0x2000;
            if (_unused6)
                ap |= 0x4000;
            if (unused7)
                ap |= 0x8000;
            writer.Write(ap);
            writer.Write(unusedbytes);
        }

        public void Setup(ushort id)
        {
            fLocked = true;
            fPrint = true;
            this.id = id;
            this._unused6 = true;
        }
    }
}